package com.zp.drug.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.drug.api.bo.DrugInfoBo;
import com.zp.drug.api.bo.DrugPriceBo;
import com.zp.drug.api.entity.DrugInfo;
import com.zp.drug.api.vo.DrugInfoVo;
import com.zp.drug.api.vo.DrugPriceVo;
import com.zp.drug.entity.bo.DrugStockBo;
import com.zp.drug.mapper.DrugInfoMapper;
import com.zp.drug.mapper.DrugStockMapper;
import com.zp.drug.service.IDrugInfoService;
import com.zp.drug.service.IDrugPriceService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 药品字典基本信息Service业务层处理
 *
 * @author zhang peng
 * @ date 2023-06-03
 */
@RequiredArgsConstructor
@Service
public class DrugInfoServiceImpl implements IDrugInfoService {

    private final DrugInfoMapper baseMapper;

    private final IDrugPriceService drugPriceService;

    private final DrugStockMapper drugStockMapper;


    /**
     * 查询药品字典基本信息
     */
    @Override
    public DrugInfoVo queryById (String id) {
        DrugInfoVo vo = baseMapper.selectVoById(id);
        if (ObjectUtil.isNotNull(vo)) {
            DrugPriceBo priceBo = new DrugPriceBo();
            priceBo.setDrugInfoId(id);
            List<DrugPriceVo> drugPriceList = drugPriceService.queryList(priceBo);
            vo.setDrugPriceList(drugPriceList);
            // 查询是否存在库存记录
            DrugStockBo drugStockBo = new DrugStockBo();
            drugStockBo.setOrgId(vo.getOrgId());
            drugStockBo.setDrugInfoId(vo.getId());
            vo.setIsExistStock(drugStockMapper.getDrugInfoCount(drugStockBo) > 0);
        }
        return vo;
    }

    /**
     * 查询药品字典基本信息列表(分页)
     */
    @Override
    public TableDataInfo<DrugInfoVo> queryPageList (DrugInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DrugInfo> lqw = buildQueryWrapper(bo);
        Page<DrugInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询药品字典基本信息列表(不分页)
     */
    @Override
    public List<DrugInfoVo> queryList (DrugInfoBo bo) {
        LambdaQueryWrapper<DrugInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DrugInfo> buildQueryWrapper (DrugInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DrugInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getDrugId()), DrugInfo::getDrugId, bo.getDrugId());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugType()), DrugInfo::getDrugType, bo.getDrugType());
        lqw.like(StringUtils.isNotBlank(bo.getDrugTypeName()), DrugInfo::getDrugTypeName, bo.getDrugTypeName());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugFrom()), DrugInfo::getDrugFrom, bo.getDrugFrom());
        lqw.like(StringUtils.isNotBlank(bo.getDrugFromName()), DrugInfo::getDrugFromName, bo.getDrugFromName());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugClass()), DrugInfo::getDrugClass, bo.getDrugClass());
        lqw.like(StringUtils.isNotBlank(bo.getDrugClassName()), DrugInfo::getDrugClassName, bo.getDrugClassName());
        lqw.like(StringUtils.isNotBlank(bo.getDrugName()), DrugInfo::getDrugName, bo.getDrugName());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugInput()), DrugInfo::getDrugInput, bo.getDrugInput());
        lqw.like(StringUtils.isNotBlank(bo.getDrugCode()), DrugInfo::getDrugCode, bo.getDrugCode());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugStandardCode()), DrugInfo::getDrugStandardCode, bo.getDrugStandardCode());
        lqw.eq(StringUtils.isNotBlank(bo.getSysDrugCode()), DrugInfo::getSysDrugCode, bo.getSysDrugCode());
        lqw.eq(StringUtils.isNotBlank(bo.getToxiProperty()), DrugInfo::getToxiProperty, bo.getToxiProperty());
        lqw.like(StringUtils.isNotBlank(bo.getToxiPropertyName()), DrugInfo::getToxiPropertyName, bo.getToxiPropertyName());
        lqw.eq(StringUtils.isNotBlank(bo.getLimitClass()), DrugInfo::getLimitClass, bo.getLimitClass());
        lqw.like(StringUtils.isNotBlank(bo.getLimitClassName()), DrugInfo::getLimitClassName, bo.getLimitClassName());
        lqw.eq(StringUtils.isNotBlank(bo.getBarCode()), DrugInfo::getBarCode, bo.getBarCode());
        lqw.eq(StringUtils.isNotBlank(bo.getSpec()), DrugInfo::getSpec, bo.getSpec());
        lqw.eq(StringUtils.isNotBlank(bo.getPackageSpec()), DrugInfo::getPackageSpec, bo.getPackageSpec());
        lqw.eq(StringUtils.isNotBlank(bo.getPackageUnits()), DrugInfo::getPackageUnits, bo.getPackageUnits());
        lqw.like(StringUtils.isNotBlank(bo.getPackageUnitName()), DrugInfo::getPackageUnitName, bo.getPackageUnitName());
        lqw.eq(StringUtils.isNotBlank(bo.getSupplierId()), DrugInfo::getSupplierId, bo.getSupplierId());
        lqw.like(StringUtils.isNotBlank(bo.getSupplierName()), DrugInfo::getSupplierName, bo.getSupplierName());
        lqw.eq(StringUtils.isNotBlank(bo.getFirmId()), DrugInfo::getFirmId, bo.getFirmId());
        lqw.like(StringUtils.isNotBlank(bo.getFirmName()), DrugInfo::getFirmName, bo.getFirmName());
        lqw.eq(StringUtils.isNotBlank(bo.getMinSpec()), DrugInfo::getMinSpec, bo.getMinSpec());
        lqw.eq(StringUtils.isNotBlank(bo.getMinUnits()), DrugInfo::getMinUnits, bo.getMinUnits());
        lqw.like(StringUtils.isNotBlank(bo.getMinUnitsName()), DrugInfo::getMinUnitsName, bo.getMinUnitsName());
        lqw.eq(bo.getPackageNum() != null, DrugInfo::getPackageNum, bo.getPackageNum());
        lqw.eq(bo.getSplitNum() != null, DrugInfo::getSplitNum, bo.getSplitNum());
        lqw.eq(bo.getDose() != null, DrugInfo::getDose, bo.getDose());
        lqw.eq(StringUtils.isNotBlank(bo.getDoseUnits()), DrugInfo::getDoseUnits, bo.getDoseUnits());
        lqw.like(StringUtils.isNotBlank(bo.getDoseUnitsName()), DrugInfo::getDoseUnitsName, bo.getDoseUnitsName());
        lqw.eq(StringUtils.isNotBlank(bo.getChannel()), DrugInfo::getChannel, bo.getChannel());
        lqw.eq(StringUtils.isNotBlank(bo.getPerformFreq()), DrugInfo::getPerformFreq, bo.getPerformFreq());
        lqw.eq(StringUtils.isNotBlank(bo.getPassNo()), DrugInfo::getPassNo, bo.getPassNo());
        lqw.eq(StringUtils.isNotBlank(bo.getIsOtc()), DrugInfo::getIsOtc, bo.getIsOtc());
        lqw.eq(StringUtils.isNotBlank(bo.getGmp()), DrugInfo::getGmp, bo.getGmp());
        lqw.eq(StringUtils.isNotBlank(bo.getBasicDrugType()), DrugInfo::getBasicDrugType, bo.getBasicDrugType());
        lqw.eq(StringUtils.isNotBlank(bo.getAntisepticType()), DrugInfo::getAntisepticType, bo.getAntisepticType());
        lqw.eq(StringUtils.isNotBlank(bo.getIsPurchase()), DrugInfo::getIsPurchase, bo.getIsPurchase());
        lqw.eq(StringUtils.isNotBlank(bo.getStorageWay()), DrugInfo::getStorageWay, bo.getStorageWay());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), DrugInfo::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), DrugInfo::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks1()), DrugInfo::getRemarks1, bo.getRemarks1());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks2()), DrugInfo::getRemarks2, bo.getRemarks2());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks3()), DrugInfo::getRemarks3, bo.getRemarks3());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks4()), DrugInfo::getRemarks4, bo.getRemarks4());
        lqw.eq(StringUtils.isNotBlank(bo.getAuditState()), DrugInfo::getAuditState, bo.getAuditState());
        lqw.like(StringUtils.isNotBlank(bo.getCountryYbName()), DrugInfo::getCountryYbName, bo.getCountryYbName());
        lqw.eq(StringUtils.isNotBlank(bo.getCountryYbCode()), DrugInfo::getCountryYbCode, bo.getCountryYbCode());
        lqw.eq(StringUtils.isNotBlank(bo.getParentId()), DrugInfo::getParentId, bo.getParentId());
        lqw.eq(StringUtils.isNotBlank(bo.getPlatformDrugInfo()), DrugInfo::getPlatformDrugInfo, bo.getPlatformDrugInfo());
        lqw.eq(StringUtils.isNotBlank(bo.getHighRisk()), DrugInfo::getHighRisk, bo.getHighRisk());
        lqw.eq(StringUtils.isNotBlank(bo.getZfOrYb()), DrugInfo::getZfOrYb, bo.getZfOrYb());
        lqw.orderByAsc(DrugInfo::getDrugClass);
        return lqw;
    }

    /**
     * 新增药品字典基本信息
     */
    @Override
    @GlobalTransactional
    public Boolean insertByBo (DrugInfoBo bo) {
        DrugInfo add = BeanUtil.toBean(bo, DrugInfo.class);
        validEntityBeforeSave(add);
        add.initEntity();
        add.setSpec(add.getMinSpec());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        saveDrugPrice(bo);
        // 添加缓存
        CacheUtils.put(CacheNames.DRUG_INFO, add.getId(), add);
        return flag;
    }

    /**
     * @return
     * @Author zhangpeng
     * @Description 保存药品价格、价表价格
     * @ date 23:00 2023/6/7
     * @Param * @param null
     **/
    @Transactional
    public Boolean saveDrugPrice (DrugInfoBo bo) {
        if (CollectionUtil.isNotEmpty(bo.getDrugPriceList())) {
            bo.getDrugPriceList().forEach(item -> {
                item.setDrugName(bo.getDrugName());
                item.setDrugInfoId(bo.getId());
                item.setOrgId(bo.getOrgId());
                item.setZfOrYb(bo.getZfOrYb());
                item.setNetworkPrice(item.getRetailPrice());
                drugPriceService.insertByBo(item);
            });
        }
        return true;
    }

    /**
     * 修改药品字典基本信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo (DrugInfoBo bo) {
        DrugInfo update = BeanUtil.toBean(bo, DrugInfo.class);
        validEntityBeforeSave(update);
        upDateDrugPrice(bo);
        boolean b = baseMapper.updateById(update) > 0;
        CacheUtils.evict(CacheNames.DRUG_INFO, update.getId());
        CacheUtils.put(CacheNames.DRUG_INFO, update.getId(), update);
        return b;
    }

    @Transactional(rollbackFor = Exception.class)
    public void upDateDrugPrice (DrugInfoBo bo) {
        drugPriceService.updatePriceList(bo);
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave (DrugInfo entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除药品字典基本信息
     */
    @Override
    public Boolean deleteWithValidByIds (Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        ids.forEach(id -> CacheUtils.evict(CacheNames.DRUG_INFO, id));
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public void refreshCache () {
        CacheUtils.clear(CacheNames.DRUG_INFO);
        List<DrugInfo> drugInfoList = baseMapper.selectList();
        List<DrugInfoVo> drugInfoVoList = BeanUtil.copyToList(drugInfoList, DrugInfoVo.class);
        drugInfoVoList.forEach(drugInfoVo -> CacheUtils.put(CacheNames.DRUG_INFO, drugInfoVo.getId(), drugInfoVo));
    }
}
